package com.acdc.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import lombok.extern.slf4j.Slf4j;

import com.acdc.dlt698.builder.ConnectRequestFrameBuilder;
import com.acdc.dlt698.domain.AddressDomain;
import com.acdc.dlt698.entity.ConnectRequestFrame;
import com.acdc.dlt698.entity.ConnectRequestData;
import com.acdc.dlt698.builder.GetRequestNormalFrameBuilder;
import com.acdc.dlt698.entity.GetRequestNormalFrame;
import com.acdc.dlt698.entity.GetRequestNormalData;
import com.acdc.dlt698.constants.OI;
import com.acdc.dlt698.constants.AttrNum;
import com.acdc.service.DLT698InstructionSender;
import com.acdc.dlt698.constants.PIID;
import com.acdc.dlt698.utils.HexUtils;
import com.acdc.mqtt.config.MqttConfig;
import com.acdc.mqtt.entity.MqttMsg;
import com.acdc.mqtt.entity.MqttMsgType;
import com.acdc.mqtt.entity.Set;
import com.acdc.mqtt.service.MqttProducerService;
import com.acdc.utils.TokenGenerator;
import com.acdc.service.IDlt698LogService;
import com.acdc.domain.Dlt698Log;
import com.acdc.domain.IotModule;
import com.acdc.service.IIotModuleService;
import java.util.Date;
import com.acdc.device.service.IMeterDeviceService;
import com.acdc.device.domain.MeterDevice;

@Slf4j
@Service
public class DLT698InstructionSenderImpl implements DLT698InstructionSender {

    // 查询服务器地址指令 68 17 00 43 45 AA AA AA AA AA AA A0 51 EA 05 01 00 40 01 02 00 00 ED 03 16
    private static final byte[] QUERY_SERVER_ADDRESS_INSTRUCTION = {0x68, 0x17, 0x00, 0x43, 0x45, (byte)0xAA, (byte)0xAA, (byte)0xAA, (byte)0xAA, (byte)0xAA, (byte)0xAA, (byte)0xA0, 0x51, (byte)0xEA, 0x05, 0x01, 0x00, 0x40, 0x01, 0x02, 0x00, 0x00, (byte)0xED, 0x03, 0x16};
    
    private static final String TOPIC_SUFFIX = "/SET";
    
    @Autowired
    private MqttConfig mqttConfig;

    @Autowired
    private ConnectRequestFrameBuilder connectRequestFrameBuilder;

    @Autowired
    private GetRequestNormalFrameBuilder getRequestNormalFrameBuilder;

    @Autowired
    private MqttProducerService mqttProducerService;

    @Autowired
    private IDlt698LogService dlt698LogService;

    @Autowired
    private IIotModuleService iotModuleService;

    @Autowired
    private IMeterDeviceService meterDeviceService;

    @Override
    public void sendConnectRequest(String imei, String serverAddress) {
        ConnectRequestFrame frame = new ConnectRequestFrame();
        AddressDomain addressDomain = new AddressDomain();
        addressDomain.setServerAddress(serverAddress);
        addressDomain.setAddressLength(5);
        frame.setAddressDomain(addressDomain);

        ConnectRequestData data = new ConnectRequestData(PIID.ZERO_ZERO, (byte)0x00);
        frame.setConnectRequestData(data);
        byte[] frameBytes = connectRequestFrameBuilder.buildFrame(frame);
        log.info("发送连接请求指令: {} - {} - {}", imei, serverAddress, HexUtils.bytesToHex(frameBytes));

        MqttMsg<Set> mqttMsg = new MqttMsg<Set>();
        mqttMsg.setStream_id(MqttMsgType.SET);
        Set setData = new Set();
        setData.setTk("1234567890");
        setData.setLen(String.valueOf(frameBytes.length));
        setData.setDat(HexUtils.bytesToHex(frameBytes).replaceAll(" ", ""));
        mqttMsg.setData(setData);
        String topic = mqttConfig.rootTopic() + imei + TOPIC_SUFFIX;
        mqttProducerService.publishMessage(topic, mqttMsg);
        
        // 保存指令日志
        saveInstructionLog(imei, serverAddress, "connect", frameBytes);
    }

    @Override
    public void queryServerAddress(String imei) {
        log.info("查询服务器地址指令: {}", imei);
        String topic = mqttConfig.rootTopic() + imei + TOPIC_SUFFIX;
        
        MqttMsg<Set> mqttMsg = new MqttMsg<Set>();
        mqttMsg.setStream_id(MqttMsgType.SET);
        Set setData = new Set();
        setData.setTk("1234567890");
        setData.setLen(String.valueOf(QUERY_SERVER_ADDRESS_INSTRUCTION.length));
        setData.setDat(HexUtils.bytesToHex(QUERY_SERVER_ADDRESS_INSTRUCTION).replaceAll(" ", ""));
        mqttMsg.setData(setData);
        mqttProducerService.publishMessage(topic, mqttMsg);
        
        // 保存指令日志
        saveInstructionLog(imei, null, "query_server_addr", QUERY_SERVER_ADDRESS_INSTRUCTION);
    }

    @Override
    public void queryForwardPower(String imei, String serverAddress, String phase) {
        log.info("查询正向有功电能指令: {}", imei);
        String topic = mqttConfig.rootTopic() + imei + TOPIC_SUFFIX;
        GetRequestNormalFrame frame = new GetRequestNormalFrame();

        AddressDomain addressDomain = new AddressDomain();
        addressDomain.setServerAddress(serverAddress);
        addressDomain.setAddressLength(5);
        frame.setAddressDomain(addressDomain);
        OI oi;
        switch(phase){
            case "A":
                oi = OI.A_PAEE;
                break;
            case "B":
                oi = OI.B_PAEE;
                break;
            case "C":
                oi = OI.C_PAEE;
                break;
            default:
                oi = OI.PAEE;
                break;
        }

        GetRequestNormalData data = new GetRequestNormalData(PIID.ZERO_ZERO, oi, 
            AttrNum.ATTR_02, (byte)0x00, (byte)0x00);
        frame.setData(data);
        byte[] frameBytes = getRequestNormalFrameBuilder.buildFrame(frame);
        
        MqttMsg<Set> mqttMsg = new MqttMsg<Set>();
        mqttMsg.setStream_id(MqttMsgType.SET);
        Set setData = new Set();
        setData.setTk("1234567890");
        setData.setLen(String.valueOf(frameBytes.length));
        setData.setDat(HexUtils.bytesToHex(frameBytes).replaceAll(" ", ""));
        mqttMsg.setData(setData);
        mqttProducerService.publishMessage(topic, mqttMsg);
        
        // 保存指令日志
        saveInstructionLog(imei, serverAddress, "power", frameBytes);
    }

    /**
     * 保存指令日志
     * @param imei IMEI号
     * @param serverAddress 服务器地址
     * @param msgType 消息类型
     * @param frameBytes 指令字节数组
     */
    private void saveInstructionLog(String imei, String serverAddress, String msgType, byte[] frameBytes) {
        try {
            IotModule iotModule = iotModuleService.selectIotModuleByImei(imei);
            if (iotModule == null) {
                log.warn("未找到IMEI为{}的IoT模块", imei);
                return;
            }
            
            MeterDevice meterDevice = null;
            if (serverAddress != null) {
                meterDevice = meterDeviceService.selectMeterDeviceByServerAddress(serverAddress);
                if (meterDevice == null) {
                    log.warn("未找到服务器地址为{}的计量设备", serverAddress);
                }
            }
            
            Dlt698Log dlt698Log = new Dlt698Log();
            dlt698Log.setIotModuleId(iotModule.getId());
            dlt698Log.setMsgType(msgType);
            dlt698Log.setDeviceId(meterDevice != null ? meterDevice.getId() : null);
            dlt698Log.setMsgData(HexUtils.bytesToHex(frameBytes).replaceAll(" ", ""));
            dlt698Log.setCreateTime(new Date());
            dlt698LogService.insertDlt698Log(dlt698Log);
            
            log.debug("成功保存指令日志: IMEI={}, 消息类型={}", imei, msgType);
        } catch (Exception e) {
            log.error("保存指令日志失败: IMEI={}, 消息类型={}, 错误信息={}", imei, msgType, e.getMessage(), e);
        }
    }
}
